package com.gukun.springboot.tdengine.service.writeplant;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.RandomUtil;
import com.gukun.springboot.tdengine.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.*;

/**
 * Generate test data
 */
public class MockDataSource implements Iterator {
    private final static Logger logger = LoggerFactory.getLogger(MockDataSource.class);
    private String tbNamePrefix;
    private int tableCount;
    private int tableIndex;
    private long maxRowsPerTable = 1000000000L;

    private int currentRow = 0;
    private int currentTbId = -1;

    private Date startDatetime = null;
    private Date endDatetime = null;
    private Integer period;
    private Integer periodType = 0;

    // interval for random period
    private Integer mnPeriod = 1;
    private Integer size = 0;

    private Integer mockType = 0;

    private Map<Integer,Date> dateMap = new HashMap<>();
    private Map<Integer,Integer> periodMap = new HashMap<>();


    public MockDataSource(String tbNamePrefix, int tableCount) {
        this.tbNamePrefix = tbNamePrefix;
        this.tableCount = tableCount;
        this.currentTbId = -1;
    }

    public MockDataSource(String tbNamePrefix,int tableIndex, int tableCount) {
        this.tableIndex = tableIndex;
        this.currentTbId = (tableIndex-1);
        this.tbNamePrefix = tbNamePrefix;
        this.tableCount = tableCount;
    }

    public MockDataSource(String tbNamePrefix,int tableIndex, int tableCount,Date startDatetime,Date endDatetime,Integer period,Integer mnPeriod,Integer periodType) {
        this.tableIndex = tableIndex;
        this.currentTbId = (tableIndex-1);
        this.tbNamePrefix = tbNamePrefix;
        this.tableCount = tableCount;
        this.startDatetime = startDatetime;
        this.endDatetime = endDatetime;
        this.period = period;
        if(periodType != null){
            this.periodType = periodType;
        }
        if(mnPeriod != null){
            this.mnPeriod = mnPeriod;
        }
    }

    public MockDataSource(String tbNamePrefix,int tableIndex, int tableCount,Date
            startDatetime,Date endDatetime,Integer period,
                          Integer mnPeriod,Integer periodType,Integer mockType) {
        this.tableIndex = tableIndex;
        this.currentTbId = (tableIndex-1);
        this.tbNamePrefix = tbNamePrefix;
        this.tableCount = tableCount;
        this.startDatetime = startDatetime;
        this.endDatetime = endDatetime;
        this.period = period;

        if(periodType != null){
            this.periodType = periodType;
        }
        if(mnPeriod != null){
            this.mnPeriod = mnPeriod;
        }
        if(mockType != null){
            this.mockType = mockType;
        }
    }

    @Override
    public boolean hasNext() {
//        currentTbId += 1;
//        if (currentTbId == (tableCount+tableIndex)) {
//            currentTbId = 0;
//            currentRow += 1;
//        }
//        String startTime = new DateTime(startMs).toString();
//        DateTime dateTime = new DateTime();
//        String currentTime = dateTime.toString();
//        if(startTime.equals(currentTime) && currentTbId == 0){
//            try{
//                dateTime.setSeconds(dateTime.getSeconds()+1);
//                long diff = dateTime.getTime()-startMs;
//                if(diff >0){
//                    Thread.sleep(diff);
//                    startMs = startMs+diff;
//                }
//            }catch(Exception e){
//                e.printStackTrace();
//            }
//            return currentRow < maxRowsPerTable;
//        }else{
//            startMs = dateTime.getTime();
//            return currentRow < maxRowsPerTable;
//        }

        currentTbId += 1;
        if (currentTbId == (tableCount+tableIndex)) {
            currentTbId = 0;
            currentRow += 1;
        }

        return currentRow < maxRowsPerTable;
    }

    @Override
    public List<String> next() {
        long startMs = System.currentTimeMillis();
        if(startDatetime != null){
            Date newDate = new DateTime(startDatetime);
            if(periodType != null){
                if(periodType == 1){
                    //随机周期
                    newDate = DateUtils.addSecondByN(startDatetime,(period*size-1) + RandomUtil.getRandom().nextInt(period)+1);
                }else{
                    //固定周期
                    newDate = DateUtils.addSecondByN(startDatetime,period*size);
                }
            }

            System.out.println("生成数据时间："+ DateUtils.formatDateTime(newDate));

            if(DateUtils.compare(endDatetime,newDate)){
                startMs = newDate.getTime();
                size++;
            }else{
                return null;
            }
        }
        long ts = startMs;
        List<String> list = new ArrayList<>();
        Integer p = 1;
        Date date = null;
        for(int i = tableIndex;i<(tableCount+tableIndex);i++){
            if(periodMap.containsKey(i)){
                p = periodMap.get(i);
            }else{
                //模拟周期
                p = RandomUtil.getRandom().nextInt(mnPeriod);
                periodMap.put(i,p);
            }
            if(dateMap.containsKey(i)){
                date = dateMap.get(i);
            }else{
                date = new Date();
                dateMap.put(i,date);
            }
            Date newDate = DateUtils.addSecondByN(date,p);
            if(DateUtils.compare(new Date(),newDate)){
                dateMap.put(i,DateUtils.parseDate(DateUtils.formatDateTime(new Date())));
                StringBuilder sb = new StringBuilder( tbNamePrefix + i + ","); // tbName
                sb.append(ts).append(','); // ts
                if(this.mockType == 0){
                    String formattedDouble = String.format("%.2f", RandomUtil.getRandom().nextDouble()*100);
                    sb.append(formattedDouble).append(',');
                }else  if(this.mockType == 1){
                    sb.append(0).append(',');
                }else if(this.mockType == 2){
                    sb.append(1).append(',');
                }else if(this.mockType == 3){
                    sb.append((RandomUtil.getRandom().nextInt(10))%2).append(',');
                }else{
//                    sb.append(RandomUtil.getRandom().nextDouble()*100).append(',');
                    String formattedDouble = String.format("%.2f", RandomUtil.getRandom().nextDouble()*100);
                    sb.append(formattedDouble).append(',');
                }
                sb.append("0");
                list.add(sb.toString());
            }

        }
        return list;

//        long ts = new DateTime().getTime();
//        StringBuilder sb = new StringBuilder(tbNamePrefix + "_" + currentTbId + ","); // tbName
//        sb.append(ts).append(','); // ts
//        sb.append((new Random()).nextDouble()*100).append(','); // current
//        sb.append("0,");
//        sb.append(currentTbId);
//        sb.append(",FLOAT");
//        return sb.toString();
    }
}
